//////////////////////////////////////////////////////////////////////////
// XPtr
template <class T>
class _XNoAddRefReleasePtr : public T
{
private:
    virtual dword AddRef() = 0;
    virtual dword Release() = 0;
};

inline xobject* ClassPtrAssign( xobject** pp, xobject* lp ) {
    if( lp != 0 )
        lp->AddRef();
    if( *pp )
        ( *pp )->Release();
    *pp = lp;
    return lp;
}

template <class T>
class xptr
{
public:
    typedef T _PtrClass;
    T* p;

    xptr() { 
        p=0; 
    }
    xptr( T* lp ) {
        if( (p = lp) != 0 )
            p->AddRef();
    }
    xptr( dword iid, xobject* lp ) {
        RESULT hr = lp->QueryClass( iid, (void**)&p );
        assert(hr==S_OK);
    }
    xptr( const xptr<T>& lp ) {
        if( (p = lp.p) != 0 )
            p->AddRef();
    }
    ~xptr() {
        if( p )
            p->Release();
    }
    inline void AddRef() {
        if( p ) {
            p->AddRef();
        }
    }
    inline void Release() {
        xobject* pTemp = p;
        if( pTemp ) {
            p = 0;
            pTemp->Release();
        }
    }
    inline operator T*() const { 
        return (T*)p; 
    }
    inline T& operator*() const { assert(p!=0); 
        return *p; 
    }
    inline T** operator&() { assert(p==0); 
        return &p; 
    }
    inline _XNoAddRefReleasePtr<T>* operator->() const { assert(p!=0);
        return (_XNoAddRefReleasePtr<T>*)p;
    }
    inline T* operator=( T* lp ) {
        return (T*)ClassPtrAssign( (xobject**)&p, lp );
    }
    inline T* operator=( const xptr<T>& lp ) {
        return (T*)ClassPtrAssign( (xobject**)&p, lp.p );
    }
    inline BOOL operator!() const {
        return (p == 0);
    }
    inline BOOL operator< ( T* pT ) const {
        return p < pT;
    }
    inline BOOL operator==( T* pT ) const {
        return p == pT;
    }
    inline void Attach(T* p2) {
        if( p )
            p->Release();
        p = p2;
    }
    inline T* Detach() {
        T* pt = p;
        p = 0;
        return pt;
    }
    BOOL CopyTo( T** ppT ) {
        assert(ppT != 0);
        if( ppT == 0 )
            return FALSE;
        *ppT = p;
        if( p )
            p->AddRef();
        return TRUE;
    }
};
